package lucene.service.impl;

import lucene.dao.IndexingGoodsDao;
import lucene.service.IndexingService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vacoor.nothing.common.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * TODO 最后更新时间,更新状态
 */
public abstract class AbstractIndexingService implements IndexingService {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractIndexingService.class);
    private SolrServer solrServer;

    /**
     * 更新 给定 id 的索引
     *
     * @param id     需要更新的 Document id
     * @param delete 是否是删除
     */
    @Override
    public void updateIndex(String id, boolean delete) {
        if (!StringUtils.hasText(id)) {
            return;
        }
        try {
            LOG.info("start update index...");

            if (delete) {
                LOG.info("delete document id: {}", id);
                solrServer.deleteById(id);
            } else {
                Object indexedBean = getIndexedBean(id);
                if (null == indexedBean) {
                    return;
                }
                SolrInputDocument doc = solrServer.getBinder().toSolrInputDocument(indexedBean);
                LOG.info("update document: {}", doc);
                solrServer.add(doc);
            }

            solrServer.commit();
        } catch (SolrServerException e) {
            LOG.error("update index failed.. {}", e);
            quietRollback(solrServer);
        } catch (IOException e) {
            LOG.error("update index failed.. {}", e);
            quietRollback(solrServer);
        }
    }

    /**
     * 重建索引
     */
    @Override
    public void rebuildIndex() {
        LOG.info("start rebuild index...");
        try {
            solrServer.deleteByQuery("*:*");

            long count = countIndexedBeans();
            if (1 > count) {
                return;
            }

            int size = 1000;
            for (int offset = 0; offset < count; offset += size) {
                LOG.info("update {} to {}", offset, offset + size);
                List<?> beans = getPagedIndexedBeans(offset, size);
                if (null != beans) {
                    System.out.println(beans.size());
                    solrServer.addBeans(beans);
                }
            }
            solrServer.commit();
            LOG.info("rebuild index complete, total: {}", count);
        } catch (IOException e) {
            LOG.error("rebuild index failed", e);
            quietRollback(solrServer);
        } catch (SolrServerException e) {
            LOG.error("rebuild index failed: {}", e);
            quietRollback(solrServer);
        }
    }

    @Override
    public void truncate() {
        try {
            solrServer.deleteByQuery("*:*");
            solrServer.commit();
        } catch (IOException e) {
            LOG.error("truncate index failed", e);
            quietRollback(solrServer);
        } catch (SolrServerException e) {
            LOG.error("truncate index failed: {}", e);
            quietRollback(solrServer);
        }
    }

    private void quietRollback(SolrServer solrServer) {
        try {
            solrServer.rollback();
        } catch (SolrServerException ignore) {
        } catch (IOException ignore) {
        }
    }

    protected abstract Object getIndexedBean(String id);

    protected abstract long countIndexedBeans();

    protected abstract List<?> getPagedIndexedBeans(int offset, int size);

    public SolrServer getSolrServer() {
        return solrServer;
    }

    public void setSolrServer(SolrServer solrServer) {
        this.solrServer = solrServer;
    }

    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = sf.openSession();
        IndexingGoodsDao mapper = session.getMapper(IndexingGoodsDao.class);

        String url = "http://192.168.1.123:8080/solr/noahs";
        SolrServer solrServer = new HttpSolrServer(url);
        NoahsIndexingServiceImpl indexingService = new NoahsIndexingServiceImpl();
        indexingService.setSolrServer(solrServer);
        indexingService.setIndexingGoodsDao(mapper);

        indexingService.rebuildIndex();
        System.out.println();
    }
}
